package com.util;

import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * AIKA
 */

public class ModelUtil extends BeanUtils {

    /**
     * 有返回值的copy
     */
    public static <T> T copy(Object source, T target) {
        if (source == null || target == null) {
            return target;
        }
        copyProperties(source, target);
        return target;
    }

    /**
     * 先copy属性,再用随机值填充model的空值
     */
    @SneakyThrows
    public static <T> T copyAndFill(Object source, T target) {
        if (source == null || target == null) {
            return target;
        }
        copyProperties(source, target);
        fillModel(target);
        return target;
    }

    /**
     * 只复制tacget属性值为空的值
     */
    @SneakyThrows
    public static <T> T copyFieldIfNull(Object source, T target) {
        if (source == null || target == null) {
            return target;
        }
        Field[] fields = target.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object targetValue = field.get(target);
            if (targetValue == null) {
                Field sourceField = source.getClass().getDeclaredField(field.getName());
                sourceField.setAccessible(true);
                Object sourceValue = sourceField.get(source);
                if (field.getType().isAssignableFrom(sourceField.getType())) {
                    field.set(target, sourceValue);
                }
            }
        }
        return target;
    }

    /**
     * 用随机值填充model的空值
     */
    @SneakyThrows
    public static <T> T fillModel(T model) {
        if (model == null) {
            return model;
        }
        Class<?> clazz = model.getClass();
        List<Field> list = Arrays.asList(clazz.getDeclaredFields());
        for (Field field : list) {
            field.setAccessible(true);
            Object value = field.get(model);
            if (value == null) {
                randomField(field, model);
            }
        }
        return model;
    }

    /**
     * 生成一个属性值随机的model
     */
    @SneakyThrows
    public static <T> T randomModel(Class<T> clazz) {
        T instance = clazz.newInstance();
        List<Field> list = Arrays.asList(clazz.getDeclaredFields());
        for (Field s : list) {
            randomField(s, instance);
        }
        return instance;
    }

    @SneakyThrows
    private static <T> void self(Field s, T instance) {
        if ("id".equals(s.getName())) {
            s.set(instance, Generator.randomChar(4));
        }
        if ("delFlag".equals(s.getName())) {
            s.set(instance, 0);
        }
        if ("sex".equals(s.getName())) {
            s.set(instance, Integer(3).toString());
        }
        if ("contractType".equals(s.getName())) {
            s.set(instance, IntegerNoZero(4).toString());
        }
        if ("alertType".equals(s.getName())) {
            s.set(instance, IntegerNoZero(4).toString());
        }
        if ("relactionType".equals(s.getName())) {
            s.set(instance, IntegerNoZero(4).toString());
        }
        if ("ownId".equals(s.getName())) {
            s.set(instance, Long.valueOf(IntegerNoZero(4).toString()));
        }

    }

    @SneakyThrows
    public static <T> T randomModel(T model) {
        List<Field> list = Arrays.asList(model.getClass().getDeclaredFields());
        for (Field field : list) {
            randomField(field, model);
        }
        return model;
    }





    @SneakyThrows
    private static <T> void randomField(Field s, T instance) {
        s.setAccessible(true);
        Class<?> type = s.getType();
        if (type.isAssignableFrom(String.class)) {
            s.set(instance, s.getName() + Integer(100).toString());
        }
        if (type.isAssignableFrom(Integer.class)) {
            s.set(instance, Integer(100));
        }
        if (type.isAssignableFrom(Long.class)) {
            s.set(instance, Long.valueOf(Integer(100)));
        }
        if (type.isAssignableFrom(BigDecimal.class)) {
            s.set(instance, new BigDecimal(Integer(100)));
        }
        if (type.isAssignableFrom(Date.class)) {
            s.set(instance, Date());
        }
        if (type.isAssignableFrom(LocalDate.class)) {
            s.set(instance, LocalDate());
        }
        if (type.isAssignableFrom(LocalDateTime.class)) {
            s.set(instance, LocalDateTime());
        }
        if ("id".equals(s.getName())) {
            s.set(instance, null);
        }
        self(s, instance);
    }


    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Integer(2));
        }
    }

    /**
     * 随机生成n个小写字母
     */
    public static String randomChar(int size) {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < size; i++) {
            char randomChar = (char) (random.nextInt(26) + 'a');
            sb.append(randomChar);
        }
        return sb.toString();
    }

    public static String ChineseName() {
        StringBuilder chineseName = new StringBuilder();
        // Unicode范围：4e00-9fa5 是中文字符的范围
        int unicodeStart = 0x4e00;
        int unicodeEnd = 0x5fa5;
        Random random = new Random();
        //参数控制生成名字的长度（2个字/3个字）
        for (int i = 0; i < random.nextInt(2) + 2; i++) {
            // 生成随机中文字符
            char randomChar = (char) (unicodeStart + random.nextInt(unicodeEnd - unicodeStart + 1));
            chineseName.append(randomChar);
        }
        return chineseName.toString();
    }


    private static Integer Integer(Integer size) {
        Random random = new Random();
        return random.nextInt(size);
    }

    private static Integer IntegerNoZero(Integer size) {
        Random random = new Random();
        return random.nextInt(size) + 1;
    }

    private static Date Date() {
        long minDay = Timestamp.valueOf("1970-01-01 00:00:00").getTime();
        long maxDay = Timestamp.valueOf("2025-01-01 00:00:00").getTime();
        long randomDay = minDay + (long) (Math.random() * (maxDay - minDay));
        return new Date(randomDay);
    }

    private static LocalDate LocalDate() {
        long minDay = LocalDate.of(1970, 1, 1).toEpochDay();
        long maxDay = LocalDate.of(2025, 1, 1).toEpochDay();
        long randomDay = minDay + (long) (Math.random() * (maxDay - minDay));
        return LocalDate.ofEpochDay(randomDay);
    }

    private static LocalDateTime LocalDateTime() {
        long minDay = LocalDate.of(1970, 1, 1).toEpochDay();
        long maxDay = LocalDate.of(2025, 1, 1).toEpochDay();
        long randomDay = minDay + (long) (Math.random() * (maxDay - minDay));
        long randomSecond = (long) (Math.random() * 24 * 60 * 60);
        return LocalDateTime.ofEpochSecond(randomSecond, 0, ZoneOffset.UTC).plusDays(randomDay);
    }

}
